<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>MyClock</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
        <style>
            * {  
                border: 0;  
                box-sizing: border-box;  
                margin: 0;  
                padding: 0;  
           }  
           :root {  
                --hue: 223;  
                --bg: hsl(var(--hue),10%,90%);  
                --fg: hsl(var(--hue),10%,10%);  
                font-size: calc(16px + (24 - 16) * (100vw - 320px) / (1280 - 320));  
           }  
           body, button {  
                color: var(--fg);  
                font: 1em/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;  
           }  
           body {  
                background-color: var(--bg);  
                height: 100vh;  
                display: grid;  
                place-items: center;  
           }  
           .progress-clock {  
                display: grid;  
                justify-content: center;  
                align-content: center;  
                position: relative;  
                text-align: center;  
                width: 16em;  
                height: 16em;  
           }  
           .progress-clock__time-date,  
           .progress-clock__time-digit,  
           .progress-clock__time-colon,  
           .progress-clock__time-ampm {  
                transition: color 0.2s linear;  
                -webkit-user-select: none;  
                -moz-user-select: none;  
                user-select: none;  
           }  
           .progress-clock__time-date,  
           .progress-clock__time-digit {  
                background: transparent;  
           }  
           .progress-clock__time-date,  
           .progress-clock__time-ampm {  
                grid-column: 1 / 6;  
           }  
           .progress-clock__time-date {  
                font-size: 0.75em;  
                line-height: 1.33;  
           }  
           .progress-clock__time-digit,  
           .progress-clock__time-colon {  
                font-size: 2em;  
                font-weight: 400;  
                grid-row: 2;  
           }  
           .progress-clock__time-colon {  
                line-height: 1.275;  
           }  
           .progress-clock__time-ampm {  
                cursor: default;  
                grid-row: 3;  
           }  
           .progress-clock__rings {  
                display: block;  
                position: absolute;  
                top: 0;  
                left: 0;  
                width: 100%;  
                height: 100%;  
                z-index: -1;  
           }  
           .progress-clock__ring {  
                opacity: 0.1;  
           }  
           .progress-clock__ring-fill {  
                transition:  
                     opacity 0s 0.3s linear,  
                     stroke-dashoffset 0.3s ease-in-out;  
           }  
           .progress-clock__ring-fill--360 {  
                opacity: 0;  
                stroke-dashoffset: 0;  
                transition-duration: 0.3s;  
           }  
           [data-group]:focus {  
                outline: transparent;  
           }  
           [data-units] {  
                transition: opacity 0.2s linear;  
           }  
           [data-group="d"]:focus,  
           [data-group="d"]:hover {  
                color: hsl(333,90%,55%);  
           }  
           [data-group="h"]:focus,  
           [data-group="h"]:hover {  
                color: hsl(33,90%,55%);  
           }  
           [data-group="m"]:focus,  
           [data-group="m"]:hover {  
                color: hsl(213,90%,55%);  
           }  
           [data-group="s"]:focus,  
           [data-group="s"]:hover {  
                color: hsl(273,90%,55%);  
           }  
           [data-group]:focus ~ .progress-clock__rings [data-units],  
           [data-group]:hover ~ .progress-clock__rings [data-units] {  
                opacity: 0.2;  
           }  
           [data-group="d"]:focus ~ .progress-clock__rings [data-units="d"],  
           [data-group="d"]:hover ~ .progress-clock__rings [data-units="d"],  
           [data-group="h"]:focus ~ .progress-clock__rings [data-units="h"],  
           [data-group="h"]:hover ~ .progress-clock__rings [data-units="h"],  
           [data-group="m"]:focus ~ .progress-clock__rings [data-units="m"],  
           [data-group="m"]:hover ~ .progress-clock__rings [data-units="m"],  
           [data-group="s"]:focus ~ .progress-clock__rings [data-units="s"],  
           [data-group="s"]:hover ~ .progress-clock__rings [data-units="s"] {  
                opacity: 1;  
           }  
           /* Dark theme */  
           @media (prefers-color-scheme: dark) {  
                :root {  
                     --bg: hsl(var(--hue),10%,10%);  
                     --fg: hsl(var(--hue),10%,90%);  
                }  
                .progress-clock__ring {  
                     opacity: 0.2;  
                }  
           }  
        </style>
    </head>
    <body>
        <div id="clock" class="progress-clock">  
            <button class="progress-clock__time-date" data-group="d" type="button">  
                 <small data-unit="w">Sunday</small><br>  
                 <span data-unit="mo">January</span>  
                 <span data-unit="d">1</span>  
            </button>  
            <button class="progress-clock__time-digit" data-unit="h" data-group="h" type="button">12</button><span class="progress-clock__time-colon">:</span><button class="progress-clock__time-digit" data-unit="m" data-group="m" type="button">00</button><span class="progress-clock__time-colon">:</span><button class="progress-clock__time-digit" data-unit="s" data-group="s" type="button">00</button>  
            <span class="progress-clock__time-ampm" data-unit="ap">AM</span>  
            <svg class="progress-clock__rings" width="256" height="256" viewBox="0 0 256 256">  
                 <defs>  
                      <linearGradient id="pc-red" x1="1" y1="0.5" x2="0" y2="0.5">  
                           <stop offset="0%" stop-color="hsl(343,90%,55%)" />  
                           <stop offset="100%" stop-color="hsl(323,90%,55%)" />  
                      </linearGradient>  
                      <linearGradient id="pc-yellow" x1="1" y1="0.5" x2="0" y2="0.5">  
                           <stop offset="0%" stop-color="hsl(43,90%,55%)" />  
                           <stop offset="100%" stop-color="hsl(23,90%,55%)" />  
                      </linearGradient>  
                      <linearGradient id="pc-blue" x1="1" y1="0.5" x2="0" y2="0.5">  
                           <stop offset="0%" stop-color="hsl(223,90%,55%)" />  
                           <stop offset="100%" stop-color="hsl(203,90%,55%)" />  
                      </linearGradient>  
                      <linearGradient id="pc-purple" x1="1" y1="0.5" x2="0" y2="0.5">  
                           <stop offset="0%" stop-color="hsl(283,90%,55%)" />  
                           <stop offset="100%" stop-color="hsl(263,90%,55%)" />  
                      </linearGradient>  
                 </defs>  
                 <!-- Days of Month -->  
                 <g data-units="d">  
                      <circle class="progress-clock__ring" cx="128" cy="128" r="74" fill="none" opacity="0.1" stroke="url(#pc-red)" stroke-width="12" />  
                      <circle class="progress-clock__ring-fill" data-ring="mo" cx="128" cy="128" r="74" fill="none" stroke="url(#pc-red)" stroke-width="12" stroke-dasharray="465 465" stroke-dashoffset="465" stroke-linecap="round" transform="rotate(-90,128,128)" />  
                 </g>  
                 <!-- Hours of Day -->  
                 <g data-units="h">  
                      <circle class="progress-clock__ring" cx="128" cy="128" r="90" fill="none" opacity="0.1" stroke="url(#pc-yellow)" stroke-width="12" />  
                      <circle class="progress-clock__ring-fill" data-ring="d" cx="128" cy="128" r="90" fill="none" stroke="url(#pc-yellow)" stroke-width="12" stroke-dasharray="565.5 565.5" stroke-dashoffset="565.5" stroke-linecap="round" transform="rotate(-90,128,128)" />  
                 </g>  
                 <!-- Minutes of Hour -->  
                 <g data-units="m">  
                      <circle class="progress-clock__ring" cx="128" cy="128" r="106" fill="none" opacity="0.1" stroke="url(#pc-blue)" stroke-width="12" />  
                      <circle class="progress-clock__ring-fill" data-ring="h" cx="128" cy="128" r="106" fill="none" stroke="url(#pc-blue)" stroke-width="12" stroke-dasharray="666 666" stroke-dashoffset="666" stroke-linecap="round" transform="rotate(-90,128,128)" />  
                 </g>  
                 <!-- Seconds of Minute -->  
                 <g data-units="s">  
                      <circle class="progress-clock__ring" cx="128" cy="128" r="122" fill="none" opacity="0.1" stroke="url(#pc-purple)" stroke-width="12" />  
                      <circle class="progress-clock__ring-fill" data-ring="m" cx="128" cy="128" r="122" fill="none" stroke="url(#pc-purple)" stroke-width="12" stroke-dasharray="766.5 766.5" stroke-dashoffset="766.5" stroke-linecap="round" transform="rotate(-90,128,128)" />  
                 </g>  
            </svg>  
       </div>
        <script>
            window.addEventListener("DOMContentLoaded",() => {  
                const clock = new ProgressClock("#clock");  
           });  
           class ProgressClock {  
                constructor(qs) {  
                     this.el = document.querySelector(qs);  
                     this.time = 0;  
                     this.updateTimeout = null;  
                     this.ringTimeouts = [];  
                     this.update();  
                }  
                getDayOfWeek(day) {  
                     switch (day) {  
                          case 1:  
                               return "Monday";  
                          case 2:  
                               return "Tuesday";  
                          case 3:  
                               return "Wednesday";  
                          case 4:  
                               return "Thursday";  
                          case 5:  
                               return "Friday";  
                          case 6:  
                               return "Saturday";  
                          default:  
                               return "Sunday";  
                     }  
                }  
                getMonthInfo(mo,yr) {  
                     switch (mo) {  
                          case 1:  
                               return { name: "February", days: yr % 4 === 0 ? 29 : 28 };  
                          case 2:  
                               return { name: "March", days: 31 };  
                          case 3:  
                               return { name: "April", days: 30 };  
                          case 4:  
                               return { name: "May", days: 31 };  
                          case 5:  
                               return { name: "June", days: 30 };  
                          case 6:  
                               return { name: "July", days: 31 };  
                          case 7:  
                               return { name: "August", days: 31 };  
                          case 8:  
                               return { name: "September", days: 30 };  
                          case 9:  
                               return { name: "October", days: 31 };  
                          case 10:  
                               return { name: "November", days: 30 };  
                          case 11:  
                               return { name: "December", days: 31 };  
                          default:  
                               return { name: "January", days: 31 };  
                     }  
                }  
                update() {  
                     this.time = new Date();  
                     if (this.el) {  
                          // date and time  
                          const dayOfWeek = this.time.getDay();  
                          const year = this.time.getFullYear();  
                          const month = this.time.getMonth();  
                          const day = this.time.getDate();  
                          const hr = this.time.getHours();  
                          const min = this.time.getMinutes();  
                          const sec = this.time.getSeconds();  
                          const dayOfWeekName = this.getDayOfWeek(dayOfWeek);  
                          const monthInfo = this.getMonthInfo(month,year);  
                          const m_progress = sec / 60;  
                          const h_progress = (min + m_progress) / 60;  
                          const d_progress = (hr + h_progress) / 24;  
                          const mo_progress = ((day - 1) + d_progress) / monthInfo.days;  
                          const units = [  
                               {  
                                    label: "w",  
                                    value: dayOfWeekName  
                               },  
                               {  
                                    label: "mo",  
                                    value: monthInfo.name,  
                                    progress: mo_progress  
                               },  
                               {  
                                    label: "d",   
                                    value: day,  
                                    progress: d_progress  
                               },  
                               {  
                                    label: "h",   
                                    value: hr > 12 ? hr - 12 : hr,  
                                    progress: h_progress  
                               },  
                               {  
                                    label: "m",   
                                    value: min < 10 ? "0" + min : min,  
                                    progress: m_progress  
                               },  
                               {  
                                    label: "s",   
                                    value: sec < 10 ? "0" + sec : sec  
                               },  
                               {  
                                    label: "ap",  
                                    value: hr > 12 ? "PM" : "AM"  
                               }  
                          ];  
                          // flush out the timeouts  
                          this.ringTimeouts.forEach(t => {  
                               clearTimeout(t);  
                          });  
                          this.ringTimeouts = [];  
                          // update the display  
                          units.forEach(u => {  
                               // rings  
                               const ring = this.el.querySelector(`[data-ring="${u.label}"]`);  
                               if (ring) {  
                                    const strokeDashArray = ring.getAttribute("stroke-dasharray");  
                                    const fill360 = "progress-clock__ring-fill--360";  
                                    if (strokeDashArray) {  
                                         // calculate the stroke  
                                         const circumference = +strokeDashArray.split(" ")[0];  
                                         const strokeDashOffsetPct = 1 - u.progress;  
                                         ring.setAttribute(  
                                              "stroke-dashoffset",  
                                              strokeDashOffsetPct * circumference  
                                         );  
                                         // add the fade-out transition, then remove it  
                                         if (strokeDashOffsetPct === 1) {  
                                              ring.classList.add(fill360);  
                                              this.ringTimeouts.push(  
                                                   setTimeout(() => {  
                                                        ring.classList.remove(fill360);  
                                                   }, 600)  
                                              );  
                                         }  
                                    }  
                               }  
                               // digits  
                               const unit = this.el.querySelector(`[data-unit="${u.label}"]`);  
                               if (unit)  
                                    unit.innerText = u.value;  
                          });  
                     }  
                     clearTimeout(this.updateTimeout);  
                     this.updateTimeout = setTimeout(this.update.bind(this),1e3);  
                }  
           }  
        </script>
    </body>
</html>
